home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / textual / pdftops / xpdf / c++ / GfxFont < prev    next >
Text File  |  1996-06-08  |  7KB  |  274 lines

  1. //========================================================================
  2. //
  3. // GfxFont.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8.  
  9. #ifdef __GNUC__
  10. //#pragma implementation
  11. #endif
  12.  
  13. #include <stdlib.h>
  14. #include <stddef.h>
  15. #include <string.h>
  16. #include "GString.h"
  17. #include "gmem.h"
  18. #include "Object.h"
  19. #include "Array.h"
  20. #include "Dict.h"
  21. #include "Error.h"
  22. #include "GfxFont.h"
  23.  
  24. #include "FontInfo.h"
  25.  
  26. //------------------------------------------------------------------------
  27. // GfxFont
  28. //------------------------------------------------------------------------
  29.  
  30. GfxFont::GfxFont(char *tag1, Dict *fontDict) {
  31.   BuiltinFont *builtinFont;
  32.   Object obj1, obj2;
  33.   int i;
  34.  
  35.   // get font tag
  36.   tag = new GString(tag1);
  37.  
  38.   // get base font name
  39.   name = NULL;
  40.   fontDict->lookup("BaseFont", &obj1);
  41.   if (obj1.isName())
  42.     name = new GString(obj1.getName());
  43.   obj1.free();
  44.  
  45.   // is it a built-in font?
  46.   builtinFont = NULL;
  47.   if (name) {
  48.     for (i = 0; i < numBuiltinFonts; ++i) {
  49.       if (!strcmp(builtinFonts[i].name, name->getCString())) {
  50.     builtinFont = &builtinFonts[i];
  51.     break;
  52.       }
  53.     }
  54.   }
  55.  
  56.   // get encoding and character widths
  57.   if (builtinFont) {
  58.     makeEncoding(fontDict, builtinFont->encoding);
  59.     makeWidths(fontDict, builtinFont->encoding, builtinFont->encodingSize,
  60.            builtinFont->widths);
  61.   } else {
  62.     makeEncoding(fontDict, NULL);
  63.     makeWidths(fontDict, NULL, 0, NULL);
  64.   }
  65.  
  66.   // get info from font descriptor
  67.   flags = 0;
  68.   fontDict->lookup("FontDescriptor", &obj1);
  69.   if (obj1.isDict()) {
  70.     obj1.dictLookup("Flags", &obj2);
  71.     if (obj2.isInt())
  72.       flags = obj2.getInt();
  73.     obj2.free();
  74.   }
  75.   obj1.free();
  76. }
  77.  
  78. int GfxFont::lookupCharName(char *name, char **enc, int encSize, int hint) {
  79.   int code;
  80.  
  81.   // check hinted code
  82.   if (enc[hint] && !strcmp(name, enc[hint]))
  83.     return hint;
  84.  
  85.   // search for it
  86.   for (code = 0; code < encSize; ++code) {
  87.     if (enc[code] && !strcmp(name, enc[code]))
  88.       return code;
  89.   }
  90.   return -1;
  91. }
  92.  
  93. double GfxFont::getWidth(GString *s) {
  94.   double w;
  95.   int i;
  96.  
  97.   w = 0;
  98.   for (i = 0; i < s->getLength(); ++i)
  99.     w += widths[s->getChar(i) & 0xff];
  100.   return w;
  101. }
  102.  
  103. void GfxFont::makeEncoding(Dict *fontDict, char **builtinEncoding) {
  104.   char **baseEncoding;
  105.   Object obj1, obj2, obj3;
  106.   int code, i;
  107.  
  108.   // start with empty encoding
  109.   for (code = 0; code < 256; ++code)
  110.     encoding[code] = NULL;
  111.  
  112.   // try to get encoding from font dict
  113.   fontDict->lookup("Encoding", &obj1);
  114.  
  115.   // MacRoman or WinAnsi encoding
  116.   if (obj1.isName("MacRomanEncoding")) {
  117.     baseEncoding = macRomanEncoding;
  118.   } else if (obj1.isName("WinAnsiEncoding")) {
  119.     baseEncoding = winAnsiEncoding;
  120.  
  121.   // custom encoding
  122.   } else if (obj1.isDict()) {
  123.     obj1.dictLookup("BaseEncoding", &obj2);
  124.     if (obj2.isName("MacRomanEncoding"))
  125.       baseEncoding = macRomanEncoding;
  126.     else if (obj2.isName("WinAnsiEncoding"))
  127.       baseEncoding = winAnsiEncoding;
  128.     else if (builtinEncoding)
  129.       baseEncoding = builtinEncoding;
  130.     else
  131.       baseEncoding = standardEncoding;
  132.     obj2.free();
  133.     obj1.dictLookup("Differences", &obj2);
  134.     if (obj2.isArray()) {
  135.       code = 0;
  136.       for (i = 0; i < obj2.arrayGetLength(); ++i) {
  137.     obj2.arrayGet(i, &obj3);
  138.     if (obj3.isInt()) {
  139.       code = obj3.getInt();
  140.     } else if (obj3.isName()) {
  141.       if (code < 256) {
  142.         gfree(encoding[code]);
  143.         encoding[code] = copyString(obj3.getName());
  144.       }
  145.       ++code;
  146.     } else {
  147.       error(0, "Wrong type in font encoding resource differences (%s)",
  148.         obj3.getTypeName());
  149.     }
  150.     obj3.free();
  151.       }
  152.     }
  153.     obj2.free();
  154.  
  155.   // built-in font encoding
  156.   } else if (builtinEncoding) {
  157.     baseEncoding = builtinEncoding;
  158.     if (!obj1.isNull())
  159.       error(0, "Font encoding is wrong type (%s)", obj1.getTypeName());
  160.  
  161.   // default encoding
  162.   } else {
  163.     if (obj1.isName())
  164.       error(0, "Unknown font encoding '%s'", obj1.getName());
  165.     else if (!obj1.isNull())
  166.       error(0, "Font encoding is wrong type (%s)", obj1.getTypeName());
  167.     baseEncoding = standardEncoding;
  168.   }
  169.  
  170.   // free the font dict encoding
  171.   obj1.free();
  172.  
  173.   // merge base encoding and differences
  174.   for (code = 0; code < 256; ++code) {
  175.     if (!encoding[code] && baseEncoding[code])
  176.       encoding[code] = copyString(baseEncoding[code]);
  177.   }
  178. }
  179.  
  180. void GfxFont::makeWidths(Dict *fontDict, char **builtinEncoding,
  181.              int builtinEncodingSize, Gushort *builtinWidths) {
  182.   Object obj1, obj2;
  183.   int firstChar, lastChar;
  184.   int code, code2;
  185.   double scale;
  186.  
  187.   // use widths from built-in font
  188.   if (builtinEncoding) {
  189.     for (code = 0; code < 256; ++code) {
  190.       code2 = lookupCharName(encoding[code], builtinEncoding,
  191.                  builtinEncodingSize, code);
  192.       if (code2 >= 0)
  193.     widths[code] = (code2 >= 0) ? (builtinWidths[code2] / 1000.0) : 0.0;
  194.     }
  195.  
  196.   // get widths from font dict
  197.   } else {
  198.     fontDict->lookup("FirstChar", &obj1);
  199.     firstChar = obj1.isInt() ? obj1.getInt() : 0;
  200.     obj1.free();
  201.     fontDict->lookup("LastChar", &obj1);
  202.     lastChar = obj1.isInt() ? obj1.getInt() : 255;
  203.     obj1.free();
  204.     for (code = 0; code < 256; ++code)
  205.       widths[code] = 0;
  206.     fontDict->lookup("Widths", &obj1);
  207.     if (obj1.isArray()) {
  208.       for (code = firstChar; code < lastChar; ++code) {
  209.     obj1.arrayGet(code - firstChar, &obj2);
  210.     if (obj2.isNum())
  211.       widths[code] = obj2.getNum() / 1000;
  212.     obj2.free();
  213.       }
  214.     } else {
  215.       error(0, "No character widths resource for non-builtin font");
  216.       for (code = 0; code < 255; ++code)
  217.     widths[code] = 0.3;
  218.     }
  219.     obj1.free();
  220.   }
  221. }
  222.  
  223. GfxFont::~GfxFont() {
  224.   int i;
  225.  
  226.   delete tag;
  227.   if (name)
  228.     delete name;
  229.   for (i = 0; i < 256; ++i) {
  230.     if (encoding[i])
  231.       gfree(encoding[i]);
  232.   }
  233. }
  234.  
  235. //------------------------------------------------------------------------
  236. // GfxFontDict
  237. //------------------------------------------------------------------------
  238.  
  239. GfxFontDict::GfxFontDict(Dict *fontDict) {
  240.   int i;
  241.   Object obj;
  242.  
  243.   numFonts = fontDict->getLength();
  244.   fonts = (GfxFont **)gmalloc(numFonts * sizeof(GfxFont *));
  245.   for (i = 0; i < numFonts; ++i) {
  246.     fontDict->getVal(i, &obj);
  247.     if (obj.isDict("Font")) {
  248.       fonts[i] = new GfxFont(fontDict->getKey(i), obj.getDict());
  249.     } else {
  250.       error(0, "font resource is not a dictionary");
  251.       fonts[i] = NULL;
  252.     }
  253.     obj.free();
  254.   }
  255. }
  256.  
  257. GfxFontDict::~GfxFontDict() {
  258.   int i;
  259.  
  260.   for (i = 0; i < numFonts; ++i)
  261.     delete fonts[i];
  262.   gfree(fonts);
  263. }
  264.  
  265. GfxFont *GfxFontDict::lookup(char *tag) {
  266.   int i;
  267.  
  268.   for (i = 0; i < numFonts; ++i) {
  269.     if (fonts[i]->matches(tag))
  270.       return fonts[i];
  271.   }
  272.   return NULL;
  273. }
  274.